﻿///////////////////////////////////////////////////////////////
//                                                           //
// Code from Arcanea Project.                                //
//                                                           //
// Please include this license part to every reproduction    //
//   of code.                                                //
//                                                           //
// This code is under Ms-RL license                          //
//                                                           //
// Please read futher information about the license,         //
//   the project (news and updates) and the                  //
//   contributors on the address :                           //
//     http://www.codeplex.com/Arcanea/                      //
//                                                           //
///////////////////////////////////////////////////////////////
using System;
using System.Collections.Generic;
//using System.Linq;
using System.Text;
using Arcanea.Mediator.BinaryClasses;
using Arcanea.Mediator.XmlClasses;

namespace Arcanea.Mediator.FullClasses
{
    /// <summary>
    /// Paquet "complet" qui contient le paquet simple pour le réseau(BinPacket) ainsi que sa définition(XmlPacket).
    /// </summary>
    public class FullPacket
    {
        BinPacket binaryFrame = null;
        XmlPacket xmlFrame = null;

        /// <summary>
        /// Paquet ne contenant que les informations utiles
        /// </summary>
        public BinPacket BinaryFrame
        {
            get
            {
                return binaryFrame;
            }
        }

        /// <summary>
        /// Paquet contenant les metadonnee (types, tailles, ...)
        /// </summary>
        public XmlPacket XmlFrame
        {
            get
            {
                return xmlFrame;
            }
        }

        /// <summary>
        /// Constructeur a partir des deux constituants essentiels
        /// </summary>
        /// <param name="binP">paquet "binaires"</param>
        /// <param name="xmlP">paquet "meta"</param>
        public FullPacket(BinPacket binP, XmlPacket xmlP)
        {
            binaryFrame = binP;
            xmlFrame = xmlP;
            verifyIntegrity();
        }

        /// <summary>
        /// Accesseur a une valeur du paquet
        /// </summary>
        /// <param name="name">nom indexeur de la valeur</param>
        /// <returns>l'objet lui meme</returns>
        public object this[string name]
        {
            get
            {
                return binaryFrame.values[IndexOf(name)];
            }
            set
            {
                binaryFrame.values[IndexOf(name)] = value;
            }
        }

        /// <summary>
        /// Nom du paquet
        /// </summary>
        public string Name
        {
            get { return xmlFrame.Name; }
        }

        /// <summary>
        /// Si c'est un tableau, retourne sa taille
        /// </summary>
        public int FieldsArraySize
        {
            get { return binaryFrame.values.Length; }
        }

        /// <summary>
        /// Retourne les descriptions de tous les champs
        /// </summary>
        public IList<XmlField> FieldsDescription
        {
            get { return xmlFrame.Fields; }
        }

        /// <summary>
        /// Retourne l'index d'une valeur, sinon leve une exception
        /// </summary>
        /// <param name="name">Nom de la valeur a rechercher</param>
        /// <returns>l'index de la valeur</returns>
        private int IndexOf(string name)
        {
            for(int i = 0 ; i < xmlFrame.Fields.Count ; i++)
            {
                if (name == xmlFrame.Fields[i].Name)
                    return i;
            }

            throw new Exception("Impossible de trouver la propriété " + name);
        }

        /// <summary>
        /// Verifie l'integrite du paquet :
        /// verifie la correspondance entre le binaire et sa definition
        /// </summary>
        /// <returns>true en cas de non probleme</returns>
        private bool verifyIntegrity()
        {
            //Comparaison des tailles
            if (xmlFrame == null || binaryFrame == null || binaryFrame.values == null || xmlFrame.Fields == null || xmlFrame.Fields.Count != binaryFrame.values.Length)
                return false;

            return true;
        }

        /// <summary>
        /// Clone l'instance actuelle
        /// </summary>
        /// <returns>Le paquet clone</returns>
        public FullPacket Clone()
        {
            FullPacket temp = CloneEmpty();
            this.binaryFrame.values.CopyTo(temp.binaryFrame.values, 0);
            return temp;

        }

        /// <summary>
        /// Clone le paquet actuel mais sans y affectuer les donnees
        /// </summary>
        /// <returns>Le paquet clone</returns>
        public FullPacket CloneEmpty()
        {
            BinPacket temp = new BinPacket();
            temp.Id = binaryFrame.Id;
            temp.values = new object[binaryFrame.values.Length];

            return new FullPacket(temp, xmlFrame);

        }

    }
}
